/**
 * n8n API 客户端库
 * 提供直接调用 n8n REST API 的功能
 */

import { logger } from '../../utils/logger.js';
import {
  N8NError,
  N8NErrorType,
  classifyN8NError,
  wrapRestCall,
  type RestResult,
} from './errors.js';

interface N8NClientConfig {
  baseUrl?: string;
  apiKey?: string;
}

interface Workflow {
  id: string;
  name: string;
  active: boolean;
  nodes?: any[];
  connections?: any;
  settings?: any;
  tags?: string[];
  createdAt?: string;
  updatedAt?: string;
  versionId?: string;
  staticData?: any;
  pinData?: any;
}

interface WorkflowHealth {
  id: string;
  name: string;
  active: boolean;
  nodeCount: number;
  connectionCount: number;
  recentExecutions: number;
  lastExecution: string | null;
  status: 'healthy' | 'inactive' | 'warning' | 'error';
  warnings?: string[];
  errors?: string[];
}

interface Execution {
  id: string;
  workflowId: string;
  status: 'success' | 'error' | 'waiting' | 'running' | 'canceled';
  mode: 'manual' | 'webhook' | 'trigger' | 'internal' | 'cli';
  startedAt: string;
  stoppedAt?: string;
  data?: any;
  retryOf?: string;
  retrySuccessId?: string;
}

interface Credential {
  id: string;
  name: string;
  type: string;
  nodesAccess?: Array<{ nodeType: string; date: string }>;
  createdAt?: string;
  updatedAt?: string;
}

interface Tag {
  id: string;
  name: string;
  createdAt?: string;
  updatedAt?: string;
}

interface NodeType {
  name: string;
  displayName: string;
  description?: string;
  version: number;
  defaults?: any;
  inputs?: string[];
  outputs?: string[];
  properties?: any[];
  credentials?: any[];
  maxNodes?: number;
  polling?: boolean;
  supportsCORS?: boolean;
  hidden?: boolean;
}

export class N8NClient {
  private baseUrl: string;
  private apiKey: string;
  private headers: Record<string, string>;

  constructor(config: N8NClientConfig = {}) {
    this.baseUrl = (
      config.baseUrl ||
      process.env.N8N_API_URL ||
      'http://localhost:5678/api/v1'
    ).replace(/\/$/, '');
    this.apiKey = config.apiKey || process.env.N8N_API_KEY || '';

    if (!this.apiKey) {
      throw new Error('N8N_API_KEY is required');
    }

    this.headers = {
      'Content-Type': 'application/json',
      'X-N8N-API-KEY': this.apiKey,
    };
  }

  private async request<T = any>(method: string, endpoint: string, data?: any): Promise<T> {
    const url = `${this.baseUrl}${endpoint}`;
    const options: RequestInit = {
      method,
      headers: this.headers,
    };

    if (data) {
      options.body = JSON.stringify(data);
    }

    try {
      const response = await fetch(url, options);

      if (!response.ok) {
        const errorText = await response.text();
        const errorType = classifyN8NError(response.status, errorText);

        const n8nError = new N8NError(`HTTP ${response.status}: ${errorText}`, errorType, {
          statusCode: response.status,
          method,
          url,
          requestData: data,
          responseBody: errorText,
        });

        // 记录详细的错误日志
        logger.error('N8N Client: API call failed', n8nError.toLogContext());

        throw n8nError;
      }

      const contentType = response.headers.get('content-type');
      if (contentType && contentType.includes('application/json')) {
        return (await response.json()) as T;
      }

      return (await response.text()) as any;
    } catch (error) {
      // 如果已经是N8NError，直接抛出
      if (error instanceof N8NError) {
        throw error;
      }

      // 处理网络错误等其他类型错误
      const errorType = classifyN8NError(0, '', error instanceof Error ? error : undefined);

      const n8nError = new N8NError(
        error instanceof Error ? error.message : String(error),
        errorType,
        {
          method,
          url,
          requestData: data,
          cause: error instanceof Error ? error : undefined,
        }
      );

      logger.error('N8N Client: API call failed', n8nError.toLogContext());
      throw n8nError;
    }
  }

  /**
   * 统一的REST调用包装器，确保所有API调用的错误都能被正确处理
   * @param operation 操作名称（用于错误信息）
   * @param apiCall API调用函数
   * @param context 额外的上下文信息
   */
  private async wrapApiCall<T>(
    operation: string,
    apiCall: () => Promise<T>,
    context: { method?: string; endpoint?: string; data?: any } = {}
  ): Promise<RestResult<T>> {
    return wrapRestCall(apiCall, {
      operation,
      method: context.method,
      url: context.endpoint ? `${this.baseUrl}${context.endpoint}` : undefined,
      requestData: context.data,
    });
  }

  /**
   * 获取包装后的结果，如果失败则抛出错误
   */
  private async unwrapResult<T>(result: RestResult<T>): Promise<T> {
    if (result.success && result.data !== undefined) {
      return result.data;
    }
    if (result.error) {
      throw result.error;
    }
    throw new N8NError('未知错误', N8NErrorType.UNKNOWN_ERROR);
  }

  // ========== 工作流管理 ==========

  /**
   * 获取所有工作流
   */
  async getWorkflows(): Promise<{ data: Workflow[]; count: number }> {
    return await this.request('GET', '/workflows');
  }

  /**
   * 根据ID获取工作流详情
   */
  async getWorkflow(workflowId: string): Promise<Workflow> {
    return await this.request('GET', `/workflows/${workflowId}`);
  }

  /**
   * 创建新工作流
   */
  async createWorkflow(workflow: Partial<Workflow>): Promise<Workflow> {
    return await this.request('POST', '/workflows', workflow);
  }

  /**
   * 更新工作流（支持 patch 操作）
   * 由于 n8n API 要求 PUT 请求必须包含所有必需字段，
   * 这个方法会先获取当前工作流，然后合并更新数据
   */
  async updateWorkflow(workflowId: string, workflow: Partial<Workflow>): Promise<Workflow> {
    // 先获取当前工作流的完整数据
    const currentWorkflow = await this.getWorkflow(workflowId);

    // 严格过滤节点字段，只保留API接受的字段
    const cleanNodes = (workflow.nodes ?? currentWorkflow.nodes)?.map(node => {
      // 只保留 n8n PUT API 接受的节点字段
      const cleanNode: any = {
        id: node.id,
        name: node.name,
        type: node.type,
        typeVersion: node.typeVersion,
        position: node.position,
        parameters: node.parameters || {},
      };
      
      // 可选字段，只在存在时添加
      if (node.credentials !== undefined) {
        cleanNode.credentials = node.credentials;
      }
      if (node.disabled !== undefined) {
        cleanNode.disabled = node.disabled;
      }
      if (node.notes !== undefined) {
        cleanNode.notes = node.notes;
      }
      if (node.webhookId !== undefined) {
        cleanNode.webhookId = node.webhookId;
      }
      
      return cleanNode;
    }) || [];

    // 合并更新数据：只包含 n8n API PUT 接口接受的字段
    const mergedWorkflow: any = {
      // 必需字段：始终包含
      name: workflow.name ?? currentWorkflow.name,
      nodes: cleanNodes,
      connections: workflow.connections ?? currentWorkflow.connections ?? {},
      settings: workflow.settings ?? currentWorkflow.settings ?? {},
    };

    // 特殊情况：如果只更新 active 状态且请求中只有这个字段，尝试 PATCH 方法
    const onlyActiveUpdate = Object.keys(workflow).length === 1 && 'active' in workflow;
    if (onlyActiveUpdate) {
      try {
        // 尝试使用 PATCH 方法更新 active 状态
        return await this.request('PATCH', `/workflows/${workflowId}`, { active: workflow.active });
      } catch (patchError) {
        console.warn(`PATCH /workflows/${workflowId} 失败，回退到 PUT 方法:`, (patchError as Error).message);
        // 如果 PATCH 失败，继续使用 PUT 方法
      }
    }

    // 可以更新的可选字段
    if (workflow.staticData !== undefined) {
      mergedWorkflow.staticData = workflow.staticData;
    }

    if (workflow.pinData !== undefined) {
      mergedWorkflow.pinData = workflow.pinData;
    }

    // 注意：不包含以下只读字段，它们会导致 "additional properties" 错误：
    // - id, active, tags, versionId, createdAt, updatedAt, hash
    // - homeProject, meta (在某些版本中)
    // 但是如果上面的 PATCH 失败，我们还是要包含 active 字段
    if (workflow.active !== undefined && !onlyActiveUpdate) {
      mergedWorkflow.active = workflow.active;
    }

    return await this.request('PUT', `/workflows/${workflowId}`, mergedWorkflow);
  }

  /**
   * 删除工作流
   */
  async deleteWorkflow(workflowId: string): Promise<void> {
    await this.request('DELETE', `/workflows/${workflowId}`);
  }

  /**
   * 激活工作流
   */
  async activateWorkflow(workflowId: string): Promise<void> {
    try {
      // 尝试多种激活方式
      
      // 方法 1: 尝试使用 POST 激活接口
      try {
        await this.request('POST', `/workflows/${workflowId}/activate`);
        return;
      } catch (activateError) {
        console.warn(`POST /workflows/${workflowId}/activate 失败:`, (activateError as Error).message);
      }
      
      // 方法 2: 尝试使用 PATCH 更新 active 状态
      try {
        await this.request('PATCH', `/workflows/${workflowId}`, { active: true });
        return;
      } catch (patchError) {
        console.warn(`PATCH /workflows/${workflowId} 失败:`, (patchError as Error).message);
      }
      
      // 方法 3: 使用 updateWorkflow，只传递必要的字段
      await this.updateWorkflow(workflowId, { active: true } as any);
      
    } catch (error) {
      console.error(`激活工作流 ${workflowId} 失败:`, (error as Error).message);
      throw error;
    }
  }

  /**
   * 停用工作流
   */
  async deactivateWorkflow(workflowId: string): Promise<void> {
    try {
      // 尝试多种停用方式
      
      // 方法 1: 尝试使用 POST 停用接口
      try {
        await this.request('POST', `/workflows/${workflowId}/deactivate`);
        return;
      } catch (deactivateError) {
        console.warn(`POST /workflows/${workflowId}/deactivate 失败:`, (deactivateError as Error).message);
      }
      
      // 方法 2: 尝试使用 PATCH 更新 active 状态
      try {
        await this.request('PATCH', `/workflows/${workflowId}`, { active: false });
        return;
      } catch (patchError) {
        console.warn(`PATCH /workflows/${workflowId} 失败:`, (patchError as Error).message);
      }
      
      // 方法 3: 使用 updateWorkflow，只传递必要的字段
      await this.updateWorkflow(workflowId, { active: false } as any);
      
    } catch (error) {
      console.error(`停用工作流 ${workflowId} 失败:`, (error as Error).message);
      throw error;
    }
  }

  // ========== 执行管理 ==========

  /**
   * 获取执行历史
   */
  async getExecutions(
    workflowId?: string,
    limit: number = 20
  ): Promise<{ data: Execution[]; count: number }> {
    const params = new URLSearchParams();
    if (workflowId) params.append('workflowId', workflowId);
    if (limit) params.append('limit', limit.toString());

    const endpoint = `/executions${params.toString() ? '?' + params.toString() : ''}`;
    return await this.request('GET', endpoint);
  }

  /**
   * 获取特定执行详情
   */
  async getExecution(executionId: string): Promise<Execution> {
    return await this.request('GET', `/executions/${executionId}`);
  }

  /**
   * 删除执行记录
   */
  async deleteExecution(executionId: string): Promise<void> {
    await this.request('DELETE', `/executions/${executionId}`);
  }

  /**
   * 手动执行工作流
   */
  async executeWorkflow(workflowId: string, data?: any): Promise<any> {
    const payload: any = {};
    if (data) payload.data = data;

    return await this.request('POST', `/workflows/${workflowId}/execute`, payload);
  }

  // ========== 实用工具方法 ==========

  /**
   * 根据名称查找工作流
   */
  async findWorkflowByName(name: string): Promise<Workflow | null> {
    const workflows = await this.getWorkflows();
    return workflows.data?.find(w => w.name === name) || null;
  }

  /**
   * 备份工作流到JSON文件
   */
  async backupWorkflow(workflowId: string, filename?: string): Promise<string> {
    const workflow = await this.getWorkflow(workflowId);
    const backupData = {
      workflow,
      exportDate: new Date().toISOString(),
      version: '1.0',
    };

    if (!filename) {
      const timestamp = new Date().toISOString().split('T')[0];
      filename = `workflow_${workflowId}_backup_${timestamp}.json`;
    }

    const { promises: fs } = await import('fs');
    await fs.writeFile(filename, JSON.stringify(backupData, null, 2));
    console.log(`✅ 工作流已备份到: ${filename}`);
    return filename;
  }

  /**
   * 安全更新工作流（带备份）
   */
  async safeUpdateWorkflow(workflowId: string, updates: Partial<Workflow>): Promise<Workflow> {
    console.log(`🔄 开始安全更新工作流 ${workflowId}...`);

    // 1. 备份原工作流
    const backupFile = await this.backupWorkflow(workflowId);

    try {
      // 2. 获取当前工作流
      const current = await this.getWorkflow(workflowId);

      // 3. 使用最简格式，只包含必需字段
      const updated = {
        name: current.name,
        nodes: updates.nodes || current.nodes,
        connections: updates.connections || current.connections,
        settings: updates.settings || current.settings || {},
      };

      // 4. 执行更新
      const result = await this.updateWorkflow(workflowId, updated);

      console.log(`✅ 工作流更新成功！备份文件: ${backupFile}`);
      return result;
    } catch (error) {
      console.error(`❌ 工作流更新失败，备份文件: ${backupFile}`);
      console.error('API 错误详情:', (error as Error).message);
      throw error;
    }
  }

  /**
   * 检查工作流健康状态
   */
  async checkWorkflowHealth(workflowId: string): Promise<WorkflowHealth> {
    try {
      const workflow = await this.getWorkflow(workflowId);
      const executions = await this.getExecutions(workflowId, 5);

      const health: WorkflowHealth = {
        id: workflow.id,
        name: workflow.name,
        active: workflow.active,
        nodeCount: workflow.nodes?.length || 0,
        connectionCount: Object.keys(workflow.connections || {}).length,
        recentExecutions: executions.count || 0,
        lastExecution: executions.data?.[0]?.startedAt || null,
        status: 'healthy',
      };

      // 简单的健康检查
      if (!workflow.active) {
        health.status = 'inactive';
        health.warnings = health.warnings || [];
        health.warnings.push('工作流未激活');
      }

      if (health.nodeCount === 0) {
        health.status = 'error';
        health.errors = health.errors || [];
        health.errors.push('工作流没有节点');
      }

      return health;
    } catch (error) {
      return {
        id: workflowId,
        name: '',
        active: false,
        nodeCount: 0,
        connectionCount: 0,
        recentExecutions: 0,
        lastExecution: null,
        status: 'error',
        errors: [(error as Error).message],
      };
    }
  }

  // ========== 凭据管理 ==========

  /**
   * 获取所有凭据
   */
  async getCredentials(): Promise<{ data: Credential[]; count: number }> {
    try {
      // 尝试多个可能的接口和方法
      
      // 方法 1: 尝试 GET /credentials
      try {
        return await this.request('GET', '/credentials');
      } catch (getError) {
        console.warn('尝试 GET /credentials 失败:', (getError as Error).message);
      }
      
      // 方法 2: 尝试 GET /credentials/for-sharing
      try {
        return await this.request('GET', '/credentials/for-sharing');
      } catch (getShareError) {
        console.warn('尝试 GET /credentials/for-sharing 失败:', (getShareError as Error).message);
      }
      
      // 方法 3: 尝试 POST /credentials/for-sharing (原来的方法)
      try {
        return await this.request('POST', '/credentials/for-sharing', {});
      } catch (postError) {
        console.warn('尝试 POST /credentials/for-sharing 失败:', (postError as Error).message);
      }
      
      // 所有方法都失败，抛出最后一个错误
      throw new Error('无法获取凭据列表，所有API接口都不可用');
      
    } catch (error) {
      // 如果所有接口都不可用，返回空结果而不是抛出错误
      console.warn('无法获取凭据列表，返回空结果:', (error as Error).message);
      return { data: [], count: 0 };
    }
  }

  /**
   * 获取凭据详情
   */
  async getCredential(credentialId: string): Promise<Credential> {
    return await this.request('GET', `/credentials/${credentialId}`);
  }

  /**
   * 创建新凭据
   */
  async createCredential(credential: Partial<Credential>): Promise<Credential> {
    return await this.request('POST', '/credentials', credential);
  }

  /**
   * 更新凭据
   */
  async updateCredential(
    credentialId: string,
    credential: Partial<Credential>
  ): Promise<Credential> {
    return await this.request('PUT', `/credentials/${credentialId}`, credential);
  }

  /**
   * 删除凭据
   */
  async deleteCredential(credentialId: string): Promise<void> {
    return await this.request('DELETE', `/credentials/${credentialId}`);
  }

  // ========== 标签管理 ==========

  /**
   * 获取所有标签
   */
  async getTags(): Promise<{ data: Tag[]; count: number }> {
    return await this.request('GET', '/tags');
  }

  /**
   * 创建标签
   */
  async createTag(tag: { name: string }): Promise<Tag> {
    return await this.request('POST', '/tags', tag);
  }

  /**
   * 更新标签
   */
  async updateTag(tagId: string, tag: { name: string }): Promise<Tag> {
    return await this.request('PUT', `/tags/${tagId}`, tag);
  }

  /**
   * 删除标签
   */
  async deleteTag(tagId: string): Promise<void> {
    return await this.request('DELETE', `/tags/${tagId}`);
  }

  // ========== 节点类型管理 ==========

  /**
   * 获取所有可用节点类型
   */
  async getNodeTypes(): Promise<NodeType[]> {
    // n8n v1.109.1 使用 /types/nodes.json
    const altUrl = this.baseUrl.replace('/api/v1', '/types/nodes.json');

    // 创建一个带有超时的AbortController
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 8000); // 8秒超时

    try {
      const response = await fetch(altUrl, {
        signal: controller.signal,
        headers: {
          ...this.headers,
          Accept: 'application/json',
        },
      });

      clearTimeout(timeoutId);

      if (!response.ok) {
        const errorText = await response.text();
        throw new Error(`HTTP ${response.status}: ${errorText}`);
      }

      const data = await response.json();
      return Array.isArray(data) ? data : [];
    } catch (error) {
      clearTimeout(timeoutId);

      if (error instanceof Error && error.name === 'AbortError') {
        throw new Error('获取节点类型超时，请检查n8n服务器连接状态');
      }

      // 重新抛出其他错误
      throw error;
    }
  }

  /**
   * 获取所有节点信息
   */
  async getNodes(): Promise<any[]> {
    // 与 getNodeTypes 相同，但返回更详细的信息
    return this.getNodeTypes();
  }

  /**
   * 获取特定节点类型详情
   */
  async getNodeType(nodeType: string, version?: number): Promise<NodeType> {
    // 从所有节点类型中查找
    const nodeTypes = await this.getNodeTypes();
    const node = nodeTypes.find(
      (n: any) => n.name === nodeType && (version === undefined || n.version === version)
    );

    if (!node) {
      throw new Error(`Node type '${nodeType}' not found`);
    }

    return node;
  }

  // ========== 工作流分享 ==========

  /**
   * 分享工作流
   */
  async shareWorkflow(workflowId: string): Promise<{ shareUrl: string }> {
    return await this.request('POST', `/workflows/${workflowId}/share`);
  }

  /**
   * 取消分享工作流
   */
  async unshareWorkflow(workflowId: string): Promise<void> {
    return await this.request('DELETE', `/workflows/${workflowId}/share`);
  }

  // ========== 工作流版本管理 ==========

  /**
   * 获取工作流版本历史
   */
  async getWorkflowVersions(workflowId: string): Promise<any[]> {
    return await this.request('GET', `/workflows/${workflowId}/versions`);
  }

  /**
   * 恢复到特定版本
   */
  async restoreWorkflowVersion(workflowId: string, versionId: string): Promise<Workflow> {
    return await this.request('POST', `/workflows/${workflowId}/versions/${versionId}/restore`);
  }

  // ========== 执行高级操作 ==========

  /**
   * 重试失败的执行
   */
  async retryExecution(executionId: string): Promise<Execution> {
    return await this.request('POST', `/executions/${executionId}/retry`);
  }

  /**
   * 停止正在运行的执行
   */
  async stopExecution(executionId: string): Promise<void> {
    return await this.request('POST', `/executions/${executionId}/stop`);
  }

  /**
   * 批量删除执行记录
   */
  async deleteExecutions(executionIds: string[]): Promise<void> {
    return await this.request('POST', '/executions/delete', { ids: executionIds });
  }

  // ========== 系统信息 ==========

  /**
   * 获取系统信息
   */
  async getSystemInfo(): Promise<any> {
    const systemInfoEndpoints = [
      { path: '/me', method: 'GET' as const },
      { path: '/healthz', method: 'GET' as const },
      { path: '/health', method: 'GET' as const },
      { path: '/status', method: 'GET' as const },
      { path: '/info', method: 'GET' as const },
    ];

    for (const endpoint of systemInfoEndpoints) {
      try {
        const result = await this.request(endpoint.method, endpoint.path);
        console.log(`✅ 系统信息获取成功，使用端点: ${endpoint.path}`);
        return {
          ...result,
          endpoint: endpoint.path,
          message: '系统信息获取成功',
        };
      } catch (error) {
        console.warn(`尝试 ${endpoint.method} ${endpoint.path} 失败:`, (error as Error).message);
        continue;
      }
    }

    // 所有端点都失败，返回默认信息
    console.warn('所有系统信息端点都不可用，返回默认信息');
    return {
      message: '系统信息接口不可用',
      version: 'unknown',
      instanceId: 'unknown',
      endpoint: 'none',
      status: 'unknown',
      timestamp: new Date().toISOString(),
    };
  }

  /**
   * 获取系统健康状态
   */
  async getSystemHealth(): Promise<any> {
    try {
      // 尝试获取基本状态
      const workflows = await this.getWorkflows();
      return {
        status: 'healthy',
        message: 'n8n API 正常响应',
        workflowCount: workflows.count || 0,
        timestamp: new Date().toISOString(),
      };
    } catch (error) {
      console.warn('无法获取系统健康状态:', (error as Error).message);
      return {
        status: 'unhealthy',
        message: (error as Error).message,
        timestamp: new Date().toISOString(),
      };
    }
  }

  // ========== Webhook 管理 ==========

  /**
   * 获取工作流的 Webhook URL
   */
  async getWorkflowWebhooks(workflowId: string): Promise<
    Array<{
      nodeId: string;
      nodeName: string;
      webhookId?: string;
      httpMethod: string;
      path?: string;
      webhookUrl?: string;
      testWebhookUrl?: string;
    }>
  > {
    const workflow = await this.getWorkflow(workflowId);
    const webhooks: any[] = [];

    workflow.nodes?.forEach(node => {
      // 查找所有 webhook 相关节点
      if (
        node.type?.toLowerCase().includes('webhook') ||
        node.type?.includes('Trigger') ||
        node.webhookId
      ) {
        const webhook: any = {
          nodeId: node.id,
          nodeName: node.name,
          nodeType: node.type,
          webhookId: node.webhookId || node.parameters?.path,
          httpMethod: node.parameters?.httpMethod || 'POST',
          path: node.parameters?.path || '',
          isEnabled: workflow.active || false,
        };

        // 构建 webhook URL
        if (node.webhookId) {
          const baseWebhookUrl = this.baseUrl.replace('/api/v1', '');
          webhook.webhookUrl = `${baseWebhookUrl}/webhook/${node.webhookId}`;
          webhook.testWebhookUrl = `${baseWebhookUrl}/webhook-test/${node.webhookId}`;
        } else if (node.parameters?.path) {
          const baseWebhookUrl = this.baseUrl.replace('/api/v1', '');
          webhook.webhookUrl = `${baseWebhookUrl}/webhook/${node.parameters.path}`;
          webhook.testWebhookUrl = `${baseWebhookUrl}/webhook-test/${node.parameters.path}`;
        }

        webhooks.push(webhook);
      }
    });

    return webhooks;
  }

  /**
   * 获取所有活动工作流的 Webhooks
   */
  async getAllActiveWebhooks(): Promise<
    Array<{
      workflowId: string;
      workflowName: string;
      webhooks: any[];
    }>
  > {
    const workflows = await this.getWorkflows();
    const activeWorkflows = workflows.data?.filter(w => w.active) || [];

    const results = [];
    for (const workflow of activeWorkflows) {
      const webhooks = await this.getWorkflowWebhooks(workflow.id);
      if (webhooks.length > 0) {
        results.push({
          workflowId: workflow.id,
          workflowName: workflow.name,
          webhooks,
        });
      }
    }

    return results;
  }

  /**
   * 测试 Webhook
   */
  async testWebhook(
    webhookUrl: string,
    data?: any,
    method: string = 'POST',
    headers: Record<string, string> = {}
  ): Promise<any> {
    const response = await fetch(webhookUrl, {
      method,
      headers: {
        'Content-Type': 'application/json',
        ...headers,
      },
      body: data ? JSON.stringify(data) : undefined,
    });

    if (!response.ok) {
      const errorText = await response.text();
      throw new Error(`Webhook test failed - HTTP ${response.status}: ${errorText}`);
    }

    const contentType = response.headers.get('content-type');
    if (contentType && contentType.includes('application/json')) {
      return await response.json();
    }

    return await response.text();
  }

  /**
   * 创建带 Webhook 的工作流
   */
  async createWorkflowWithWebhook(
    name: string,
    webhookPath: string,
    httpMethod: string = 'POST',
    responseMode: 'onReceived' | 'lastNode' = 'onReceived'
  ): Promise<Workflow> {
    const nodes = [
      {
        id: 'webhook_1',
        name: 'Webhook',
        type: 'n8n-nodes-base.webhook',
        typeVersion: 1,
        position: [250, 300],
        parameters: {
          httpMethod,
          path: webhookPath,
          responseMode,
          responseData: responseMode === 'lastNode' ? 'lastNodeOutput' : '',
          options: {},
        },
      },
    ];

    const workflow = await this.createWorkflow({
      name,
      nodes,
      connections: {},
      settings: {
        executionOrder: 'v1',
      },
    });

    return workflow;
  }

  /**
   * 通过Webhook执行工作流
   */
  async runWebhook(
    workflowName: string,
    data?: any,
    headers: Record<string, string> = {}
  ): Promise<any> {
    // 先找到工作流获取webhook URL
    const workflow = await this.findWorkflowByName(workflowName);
    if (!workflow) {
      throw new Error(`工作流 '${workflowName}' 未找到`);
    }

    // 查找Chat Trigger节点的webhook信息
    const chatTrigger = workflow.nodes?.find(
      node => node.type === '@n8n/n8n-nodes-langchain.chatTrigger'
    );

    if (!chatTrigger?.webhookId) {
      throw new Error(`工作流 '${workflowName}' 没有配置Chat Trigger webhook`);
    }

    // 构建webhook URL
    const webhookUrl = `${this.baseUrl.replace('/api/v1', '')}/webhook-test/${
      chatTrigger.webhookId
    }`;

    // 执行webhook调用
    const webhookHeaders = {
      'Content-Type': 'application/json',
      ...headers,
    };

    try {
      const response = await fetch(webhookUrl, {
        method: 'POST',
        headers: webhookHeaders,
        body: data ? JSON.stringify(data) : null,
      });

      if (!response.ok) {
        const errorText = await response.text();
        throw new Error(`Webhook调用失败 HTTP ${response.status}: ${errorText}`);
      }

      const contentType = response.headers.get('content-type');
      if (contentType && contentType.includes('application/json')) {
        return await response.json();
      }

      return await response.text();
    } catch (error) {
      console.error(`❌ Webhook调用失败 [${webhookUrl}]:`, (error as Error).message);
      throw error;
    }
  }
}
